package kt.com.bilin.coin.api

import android.content.Context
import androidx.lifecycle.Observer
import com.bilin.coin.utils.SafeDialogHandle
import com.kingja.loadsir.callback.SuccessCallback
import com.kingja.loadsir.core.LoadService
import kt.com.bilin.coin.ui.dialog.LoadingDialog
import kt.com.bilin.coin.bean.ResultBean
import kt.com.bilin.coin.common.toastMessageLong
import kt.com.bilin.coin.helper.loadsir.ErrorCallback
import kt.com.bilin.coin.helper.loadsir.LoadingCallback
import kt.com.bilin.coin.helper.loadsir.NotNetworkCallback
import com.scwang.smartrefresh.layout.api.RefreshLayout
import kt.com.bilin.coin.common.ARouterNavigation
import kt.com.bilin.coin.common.showLoadingBeforeSuccessCallback
import kt.com.bilin.coin.listener.RefreshListener
import kt.com.bilin.coin.listener.SmartRefreshListener
import kt.com.bilin.coin.ui.widget.CommonButton
import kt.com.bilin.coin.utils.Logger
import java.io.IOException
import java.net.SocketException


/**
 * 接口请求处理类
 */
open class ApiObserver<T>(
        private var context: Context? = null,
        private var dialog: LoadingDialog? = null,
        private val cancelable: Boolean = true,
        private val showMsg: Boolean = true,
        private val showLoadingDialog: Boolean = true,
        private var commonButton: CommonButton? = null,
        private var loadService: LoadService<*>? = null,
        refreshLayout: RefreshLayout? = null,
        private var complete: (() -> Unit)? = null,
        private var error: ((e: Throwable?) -> Unit)? = null,
        private var success: ((T?) -> Unit)? = null,
) : Observer<ApiProcess<T>> {
    private var refreshListener: RefreshListener? = null

    init {
        if (refreshLayout != null) refreshListener = SmartRefreshListener(refreshLayout)
    }

    override fun onChanged(apiProcess: ApiProcess<T>) {
        when (apiProcess.apiCode) {
            ApiCode.START -> start()
            ApiCode.SUCCESS -> success(apiProcess.data)
            ApiCode.ERROR -> onError(apiProcess.throwable)
            ApiCode.COMPLETE -> onComplete()
        }
    }

    open fun start() {
        if (loadService != null) {
            loadService?.showLoadingBeforeSuccessCallback()
        } else {
            try {
                if (dialog == null && context != null && showLoadingDialog) {
                    dialog = LoadingDialog(context!!)
                    dialog?.setCancelable(cancelable)
                }
                SafeDialogHandle.safeShowDialog(dialog)
            } catch (e: Exception) {
                Logger.e(e)
            }
        }
        commonButton?.enable(false)
    }

    open fun success(t: T?) {
        try {
            loadService?.showSuccess()
            dismiss()
            success?.invoke(t)
        } catch (e: Exception) {
            onError(e)
        }
    }

    open fun onError(e: Throwable?) {
        refreshListener?.stopRefresh()
        try {
            error?.invoke(e)
            if (showMsg) {
                if (e is FirmException) {
                    if (!doFirmError(e) && !e.message.isNullOrEmpty()) {
                        toastMessageLong(if (e.message!!.length > 100) " 服务器异常" else e.message)
                    }
                } else if (e is IOException || e is SocketException) {
                    toastMessageLong("网络连接失败")
                } else if ("kotlinx.coroutines.JobCancellationException" == e?.javaClass?.name) {
                    //toastMessageLong("网络连接失败")
                } else {
                    toastMessageLong("加载未成功")
                }
            }
            if (e is FirmException) {
                if (ResultBean.NOT_LOGIN == e.code) {
                    kotlin.runCatching { ARouterNavigation("/auction/LoginActivity") }
                }
            }
            Logger.e(e)
            doError(e)
            if (loadService != null) {
                if (e is NotNetworkException) {
                    loadService?.showCallback(NotNetworkCallback::class.java)
                } else loadService?.showCallback(ErrorCallback::class.java)
            }
        } catch (e1: Exception) {
            Logger.e(e1)
        }
        dismiss()
    }

    open fun onComplete() {
        complete?.invoke()
        refreshListener?.stopRefresh()
        commonButton?.enable(true)
    }

    /**
     * @return 业务异常是否已被处理
     */
    open fun doFirmError(e: FirmException): Boolean {
        return false
    }

    /**
     * 子类自己处理异常
     */
    open fun doError(e: Throwable?) {}

    fun onDismiss() {}

    fun dismiss() {
        SafeDialogHandle.safeDismissDialog(dialog)
        onDismiss()
    }

    fun onDestroy() {
        dismiss()
        success = null
        context = null
        dialog = null
        loadService = null
        refreshListener = null
        commonButton = null
    }
}